package com.dmwork.service.customer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dmwork.common.base.result.R;
import com.dmwork.common.base.result.ResultCodeEnum;
import com.dmwork.common.base.util.FormUtils;
import com.dmwork.common.base.util.JwtInfo;
import com.dmwork.common.base.util.JwtUtils;
import com.dmwork.common.base.util.MD5;
import com.dmwork.service.base.exception.DmworkException;
import com.dmwork.service.customer.entity.Customer;
import com.dmwork.service.customer.entity.CustomerFollower;
import com.dmwork.service.customer.entity.returnVo.CustomerBriefInfoListVo;
import com.dmwork.service.customer.entity.vo.*;
import com.dmwork.service.customer.feign.InteractionFeignService;
import com.dmwork.service.customer.feign.WorkFeignService;
import com.dmwork.service.customer.mapper.CustomerFollowerMapper;
import com.dmwork.service.customer.mapper.CustomerMapper;
import com.dmwork.service.customer.service.CustomerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dmwork.service.customer.properties.TokenProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 李天
 * @since 2021-03-10
 */
@Slf4j
@Service
@Transactional
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService {

    @Autowired
    private CustomerFollowerMapper customerFollowerMapper;

    @Autowired
    private WorkFeignService workFeignService;
    @Autowired
    private InteractionFeignService interactionFeignService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private TokenProperties tokenProperties;

    @Value("${default.space-background-location-type}")
    private String DEFAULT_SPACE_BACKGROUND_LOCATION;
    @Value("${redis.custom.expire-time.defualt-space-background-url}")
    private Integer DEFAULT_SPACE_BACKGROUND_EXPIRE;

    @Override
    public void register(RegisterVo registerVo) {
        //获取注册信息
        String name = registerVo.getName();
        String email = registerVo.getEmail();
        String code = registerVo.getCode();
        String mobile = registerVo.getMobile();
        String password = registerVo.getPassword();

        //进行后端参数合法性校验
        if (StringUtils.isEmpty(mobile)
                || !FormUtils.isMobile(mobile)
                || StringUtils.isEmpty(name)
                || !FormUtils.isName(name)
                || StringUtils.isEmpty(email)
                || !FormUtils.isEmail(email)
                || StringUtils.isEmpty(code)
                || StringUtils.isEmpty(password)) {

            throw new DmworkException(ResultCodeEnum.PARAM_ERROR);

        }

        //短信验证码验证
        Object o = redisTemplate.opsForValue().get(mobile);
        if (o != null) {
            String cacheCode= (String) o;
            if (cacheCode.equals(code)) {
                redisTemplate.delete(mobile);
            }else {
                throw new DmworkException(ResultCodeEnum.VERIFICATION_CODE_WRONG);
            }
        }else {
            throw new DmworkException(ResultCodeEnum.VERIFICATION_CODE_EMPTY_OR_NULL);
        }

        QueryWrapper<Customer> queryWrapper = null;

        int count = 0;

        //验证用户名是否已被注册
        queryWrapper = new QueryWrapper<>();
        queryWrapper = queryWrapper.eq("name", name);
        count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new DmworkException(ResultCodeEnum.REGISTER_NAME_ERROR);
        }

        //验证电话号码是否被注册
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", mobile);
        count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new DmworkException(ResultCodeEnum.REGISTER_MOBLE_ERROR);
        }

        //验证无误，将用户注册信息写入数据库
        Customer customer = new Customer();
        customer.setName(name);
        customer.setMobile(mobile);
        customer.setEmail(email);
        customer.setPassword(MD5.encrypt(password));
        customer.setAvatar(Customer.DEFAULT_AVATAR);
        customer.setSign(Customer.DEFAULT_SIGN);
        customer.setStatus(0);
        baseMapper.insert(customer);
    }

    @Override
    public String login(LoginVo loginVo) {
        //验证登录信息合法性
        if (StringUtils.isEmpty(loginVo.getMobile())
                || !FormUtils.isMobile(loginVo.getMobile())
                || StringUtils.isEmpty(loginVo.getPassword())) {
            throw new DmworkException(ResultCodeEnum.PARAM_ERROR);
        }

        //查询数据库检测手机号是否存在
        QueryWrapper<Customer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", loginVo.getMobile());
        Customer customer = baseMapper.selectOne(queryWrapper);
        if (customer == null) {
            throw new DmworkException(ResultCodeEnum.LOGIN_MOBILE_ERROR);
        }

        //通过从数据库中查询出来的用户信息，检测输入的密码是否正确
        if (!MD5.encrypt(loginVo.getPassword()).equals(customer.getPassword())) {
            throw new DmworkException(ResultCodeEnum.LOGIN_PASSWORD_ERROR);
        }

        //判断用户是否被禁用
        if (customer.getStatus() == 1) {
            throw new DmworkException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
        }

        //登录信息验证正确后，将用户非隐私基本信息编码进jwtToken中
        JwtInfo jwtInfo = new JwtInfo(customer.getId(), customer.getName(), customer.getAvatar(), customer.getSign(), customer.getColor(), customer.getTextColor());
        log.info(tokenProperties.getExpire() + "");
        return JwtUtils.getJwtToken(jwtInfo, tokenProperties.getExpire() * 24 * 60 * 60);

    }

    @Override
    public CustomerBriefInfoListVo selectFollowList(String id, String followGroupId, Integer page, Integer limit) {

        List<CustomerBriefInfoVo> briefInfoVoList = new ArrayList<>();

        //分页查出当前用户关注的所有用户id
        Page<CustomerFollower> pageParam = new Page<>(page, limit);
        log.info("page: " + page + "  limit: " + limit);
        QueryWrapper<CustomerFollower> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("follower_id", id);
        if (!followGroupId.equals("-1")) {
            queryWrapper.eq("follow_group_id", followGroupId);
        }
        Page<CustomerFollower> selectPage = customerFollowerMapper.selectPage(pageParam, queryWrapper);

        List<CustomerFollower> records = selectPage.getRecords();
        //获得关注用户的id集合
        List<String> idList = new ArrayList<>();
        for (CustomerFollower record : records) {
            log.info(record.toString());
            idList.add(record.getCustomerId());
        }
        //如果为空，说明关注用户已经遍历完毕，不再往下执行
        if (idList.isEmpty()) {
            return new CustomerBriefInfoListVo(briefInfoVoList, 0L);
        }
        //通过id集合查询出所有用户信息
        List<Customer> customerList = baseMapper.selectBatchIds(idList);
        //数据组装
        for (Customer customer : customerList) {
            CustomerBriefInfoVo infoVo = new CustomerBriefInfoVo();
            infoVo.setName(customer.getName());
            infoVo.setCustomerId(customer.getId());
            infoVo.setAvatar(customer.getAvatar());
            infoVo.setSign(customer.getSign());
            briefInfoVoList.add(infoVo);
        }
        return new CustomerBriefInfoListVo(briefInfoVoList, selectPage.getTotal());
    }

    @Override
    public CustomerBriefInfoListVo selectFansList(String id, Integer page, Integer limit) {

        List<CustomerBriefInfoVo> briefInfoVoList = new ArrayList<>();

        //分页查出关注当前用户的所有用户id
        Page<CustomerFollower> pageParam = new Page<>(page, limit);
        QueryWrapper<CustomerFollower> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("customer_id", id);
        Page<CustomerFollower> selectPage = customerFollowerMapper.selectPage(pageParam, queryWrapper);
        List<CustomerFollower> records = selectPage.getRecords();
        //获得粉丝用户的id集合
        List<String> idList = new ArrayList<>();
        for (CustomerFollower record : records) {
            idList.add(record.getFollowerId());
        }

        //如果为空，说明粉丝用户数据已经遍历完毕，不需要再往下执行
        if (idList.isEmpty()) {
            return null;
        }

        //通过id集合查询出所有用户信息
        List<Customer> customerList = baseMapper.selectBatchIds(idList);

        //查出这些粉丝用户中该用户所关注的用户（查询互关）
        queryWrapper=new QueryWrapper<CustomerFollower>();
        queryWrapper.eq("follower_id", id).in("customer_id", idList);
        List<CustomerFollower> followedCustomerList = customerFollowerMapper.selectList(queryWrapper);

        //数据组装
        for (Customer customer : customerList) {
            CustomerBriefInfoVo infoVo = new CustomerBriefInfoVo();
            infoVo.setName(customer.getName());
            infoVo.setCustomerId(customer.getId());
            infoVo.setAvatar(customer.getAvatar());
            infoVo.setSign(customer.getSign());
            //判断当前粉丝用户是否也是自己已关注的
            for (CustomerFollower follower : followedCustomerList) {
                if (customer.getId().equals(follower.getCustomerId())) {
                    infoVo.setFollowed(true);
                    break;
                }
            }
            briefInfoVoList.add(infoVo);
        }
        return new CustomerBriefInfoListVo(briefInfoVoList, selectPage.getTotal());
    }

    @Override
    public CustomerDetailInfoVo getDetailInfoById(String customerId) {
        CustomerDetailInfoVo customerDetailInfoVo = new CustomerDetailInfoVo();
        Customer customer = baseMapper.selectById(customerId);
        BeanUtils.copyProperties(customer, customerDetailInfoVo);

        QueryWrapper<CustomerFollower> queryWrapper = null;
        //查询粉丝数
        queryWrapper = new QueryWrapper<CustomerFollower>().eq("customer_id", customerId);
        Integer fansCount = customerFollowerMapper.selectCount(queryWrapper);
        customerDetailInfoVo.setFansCount(fansCount);
        //查询关注数
        queryWrapper = new QueryWrapper<CustomerFollower>().eq("follower_id", customerId);
        Integer followsCount = customerFollowerMapper.selectCount(queryWrapper);
        customerDetailInfoVo.setFollowsCount(followsCount);
        // 查询作品数
        Integer workCount = workFeignService.getWorkCountByCustomerId(customerId);
        if (workCount < 0) {
            throw new DmworkException(ResultCodeEnum.SELECT_WORK_COUNT_ERROR);
        }
        customerDetailInfoVo.setWorksCount(workCount);
        // 查询动态数
        R feedCountResult = interactionFeignService.getFeedCount(customerId);
        customerDetailInfoVo.setFeedCount((Integer) feedCountResult.getData().get("count"));

        //查询作品收藏数
        Integer collectCount = interactionFeignService.getCollectCountByCustomerId(customerId);
        if (collectCount < 0) {
            customerDetailInfoVo.setCollectCount(0);
        } else {
            customerDetailInfoVo.setCollectCount(collectCount);
        }

        return customerDetailInfoVo;
    }

    @Override
    public List<Customer> getCustomerList(Integer page, Integer limit) {
        log.info("page: " + page + " limit: " + limit);
        Page<Customer> customerPage = new Page<>(page, limit);
        Page<Customer> selectPage = baseMapper.selectPage(customerPage, null);
        selectPage.getTotal();
        return selectPage.getRecords();
    }

    @Override
    public BaseInfoVo getBaseInfoVoById(String customerId) {
        BaseInfoVo baseInfoVo = new BaseInfoVo();
        Customer customer = baseMapper.selectById(customerId);
        BeanUtils.copyProperties(customer, baseInfoVo);

        QueryWrapper<CustomerFollower> queryWrapper = null;
        //查询粉丝数
        queryWrapper = new QueryWrapper<CustomerFollower>().eq("customer_id", customerId);
        Integer fansCount = customerFollowerMapper.selectCount(queryWrapper);
        baseInfoVo.setFansCount(fansCount);
        //查询关注数
        queryWrapper = new QueryWrapper<CustomerFollower>().eq("follower_id", customerId);
        Integer followsCount = customerFollowerMapper.selectCount(queryWrapper);
        baseInfoVo.setFollowsCount(followsCount);
        // 查询作品数
        Integer workCount = workFeignService.getWorkCountByCustomerId(customerId);
        if (workCount < 0) {
            throw new DmworkException(ResultCodeEnum.SELECT_WORK_COUNT_ERROR);
        }
        baseInfoVo.setWorksCount(workCount);
        // 查询动态数
        R feedCountResult = interactionFeignService.getFeedCount(customerId);
        baseInfoVo.setFeedCount((Integer) feedCountResult.getData().get("count"));
        return baseInfoVo;
    }

    @Override
    public boolean checkDupicateInfo(Customer customer) {
        return false;
    }

    @Override
    public Page<Customer> getCustomerPage(Integer page, Integer limit, CustomerAdminQueryVo customerAdminQueryVo) {
        Page<Customer> customerPage = new Page<>(page, limit);
        QueryWrapper<Customer> queryWrapper = new QueryWrapper<>();
        if (customerAdminQueryVo.getQueryType() != null) {
            String column = null;
            switch (customerAdminQueryVo.getQueryType()) {
                case 0:
                    column = "name";
                    break;
                case 1:
                    column = "mobile";
                    break;
                case 2:
                    column = "email";
                    break;
            }
            queryWrapper.like(column, customerAdminQueryVo.getQueryString());
        }
        if (customerAdminQueryVo.getSortType() == null || customerAdminQueryVo.getSortType() == 0) {
            queryWrapper.orderByDesc("gmt_create");
        } else {
            queryWrapper.orderByAsc("gmt_create");
        }
        return baseMapper.selectPage(customerPage, queryWrapper);
    }

    @Override
    public CustomerAdminDetailInfoVo getCustomerAdminDetailInfoById(String customerId) {
        CustomerAdminDetailInfoVo customerAdminDetailInfoVo = new CustomerAdminDetailInfoVo();
        Customer customer = baseMapper.selectById(customerId);
        BeanUtils.copyProperties(customer, customerAdminDetailInfoVo);

        QueryWrapper<CustomerFollower> queryWrapper = null;
        //查询粉丝数
        queryWrapper = new QueryWrapper<CustomerFollower>().eq("customer_id", customerId);
        Integer fansCount = customerFollowerMapper.selectCount(queryWrapper);
        customerAdminDetailInfoVo.setFansCount(fansCount);

        //查询关注数
        queryWrapper = new QueryWrapper<CustomerFollower>().eq("follower_id", customerId);
        Integer followsCount = customerFollowerMapper.selectCount(queryWrapper);
        customerAdminDetailInfoVo.setFollowsCount(followsCount);

        // 查询作品数
        Integer workCount = workFeignService.getWorkCountByCustomerId(customerId);
        if (workCount < 0) {
            throw new DmworkException(ResultCodeEnum.SELECT_WORK_COUNT_ERROR);
        }
        customerAdminDetailInfoVo.setWorksCount(workCount);

        // 查询动态数
        R feedCountResult = interactionFeignService.getFeedCount(customerId);
        customerAdminDetailInfoVo.setFeedCount((Integer) feedCountResult.getData().get("count"));

        return customerAdminDetailInfoVo;
    }

    @Override
    public String getSpaceDefaultBackgroundUrl() {
        String key = "getSpaceDefaultBackgroundUrl";
        if (!redisTemplate.hasKey(key)) {
            R backgroundResult = interactionFeignService.getBackground(DEFAULT_SPACE_BACKGROUND_LOCATION);
            if (!backgroundResult.getSuccess()) {
                throw new DmworkException(ResultCodeEnum.SELECT_DEFAULT_BACKGROUND_RL_ERROR);
            }
            String backgroundUrl = (String) backgroundResult.getData().get("url");
            redisTemplate.opsForValue().set(key, backgroundUrl, DEFAULT_SPACE_BACKGROUND_EXPIRE, TimeUnit.SECONDS);
            return backgroundUrl;
        } else {
            return (String) redisTemplate.opsForValue().get(key);
        }

    }
}
